const fs = require('fs');
const { join, sep } = require('path');
// 如果该行报错，请手动安装 @babel/template
// eslint-disable-next-line import/no-extraneous-dependencies
const template = require('@babel/template');
// 如果该行报错，请手动安装 @babel/types
// eslint-disable-next-line import/no-extraneous-dependencies
const t = require('@babel/types');

const isMiniPage = (state) => {
  const pathKeyWords = state.file.opts.filename.split(sep);
  const fileName = pathKeyWords.pop().split('.')[0];
  return (
    pathKeyWords.includes('pages') &&
    fs.existsSync(
      join(
        pathKeyWords.join(sep),
        `${fileName}.config.<%= typescript
  ? 't'
  : 'j' %>s`
      )
    )
  );
};

/**
 * 为页面(小程序页面)全局注入 pageDecorator 装饰器
 */
module.exports = function injectPageDecoratorPlugin() {
  return {
    name: 'inject-page-decorator-plugin',
    visitor: {
      ClassDeclaration: {
        // todo: 不严谨，一个文件有两个class无法判断，后续优化
        enter(path, state) {
          if (isMiniPage(state)) {
            // const importTemp = template.smart('import pageDecorator from "@/utils/decorator/pageDecorator";');
            const importTemp = template.smart('import pageHoc from "@/utils/hoc/pageHoc";');
            [...path.getAllPrevSiblings(), ...path.getAllNextSiblings(), path.parentPath].forEach((nodePath) => {
              if (nodePath.isExportDefaultDeclaration() || nodePath.toString().indexOf('as default') > -1) {
                const exportTemp = template.smart(`export default pageHoc(${path.toString()})`, {
                  syntacticPlaceholders: true, // 只能使用句法占位符 %%x%% 防止与大写静态变量冲突
                  plugins: ['decorators-legacy', 'classProperties', 'jsx', 'tsx'],
                });
                nodePath.replaceWith(exportTemp());
              }
            });
            // const decoratorTemp = t.decorator(t.callExpression(t.identifier('pageDecorator'), []));
            // if (path.node.decorators) {
            //   path.node.decorators.push(decoratorTemp);
            // } else {
            //   // eslint-disable-next-line no-param-reassign
            //   path.node.decorators = [decoratorTemp];
            // }

            state.file.path.node.body.push(importTemp());
          }
        },
      },
      ExportDefaultDeclaration: {
        enter(path, state) {
          const isReactCom = (unkownPath) =>
            unkownPath.isArrowFunctionExpression() ||
            unkownPath.isFunctionExpression() ||
            unkownPath.isFunctionDeclaration();
          let hooksPage = false;
          const declaration = path.get('declaration');
          if (declaration.isIdentifier()) {
            path.getAllPrevSiblings().forEach((sibling) => {
              if (sibling.isVariableDeclaration()) {
                const varName = sibling.get('declarations.0.id').node.name;
                const varInit = sibling.get('declarations.0.init');
                if (varName === declaration.node.name && isReactCom(varInit)) {
                  hooksPage = true;
                }
              }
            });
          } else if (isReactCom(declaration)) {
            hooksPage = true;
          } else if (declaration.isAssignmentExpression()) {
            const right = declaration.get('right');
            if (isReactCom(right)) {
              hooksPage = true;
            }
          }

          if (isMiniPage(state) && (hooksPage || declaration.isClassDeclaration())) {
            const importTemp = template.smart('import pageHoc from "@/utils/hoc/pageHoc";');
            const exportTemp = template.smart(`export default pageHoc(${path.get('declaration').toString()})`, {
              syntacticPlaceholders: true, // 只能使用句法占位符 %%x%% 防止与大写静态变量冲突
              plugins: ['decorators-legacy', 'classProperties', 'jsx', 'tsx'],
            });
            state.file.path.node.body.push(importTemp());
            path.replaceWith(exportTemp());
          }
        },
      },
    },
  };
};
